home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #50 (Nov 89) / Alternate Appl / AlternateCDEF.c < prev    next >
C/C++ Source or Header  |  1989-08-19  |  35KB  |  978 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /*    Source  - AlternateCDEF.c                    */
  4. /*    Author  - Alexander S. Colwell, Copyright (C) 1988, 1989    */
  5. /*                                    */
  6. /*                                    */
  7. /*    Purpose - This is a dual-arrow scroll bar control definition    */
  8. /*          procedure. It is similiar to the standard scroll bar    */
  9. /*          except this has two arrow indicators on both ends.    */
  10. /*                                    */
  11. /*    Routine    - DSControl      : Dual scroll bar control definition.    */
  12. /*          DSInitControl  : Init the control parameters.        */
  13. /*          DSCalcThumb    : Calculate new thumb position.    */
  14. /*          DSDrawThumb    : Draw the thumb.            */
  15. /*          DSPositionThumb: Re-position the thumb.        */
  16. /*          DSSetupThumb   : Setup thumb for dragging.        */
  17. /*          DSDrawHBtn     : Draw high button.            */
  18. /*          DSDrawLBtn     : Draw low button.            */
  19. /*          DSFrameButtons : Draw high and low frames around btns.*/
  20. /*          DSTestControl  : Test for part controls.        */
  21. /*          DSSetScrollRgn : Set scroll region.            */
  22. /*          DSGetBackGround: Get back-ground color.        */
  23. /*          DSGetForeGround: Get fore-ground color.        */
  24. /*          DSSetBackGround: Set back-ground color.        */
  25. /*          DSSetForeGround: Set fore-ground color.        */
  26. /*          DSEraseRect    : Erase rect area.            */
  27. /*          DSFrameRect     : Frame rect area.            */
  28. /*          DSFillRect     : Fill rect area.            */
  29. /*          DSErasePoly    : Erase poly area.            */
  30. /*          DSFramePoly    : Frame poly area.            */
  31. /*          DSFillPoly     : Fill poly area.            */
  32. /*          DSDrawObject   : Draw object type (ie. rect or poly)    */
  33. /*                                    */
  34. /*    Revisions - 6/27/89 asc :                    */
  35. /*          * Add fixes to the calculate region relating to 32-bit*/
  36. /*            clean rules in Technical Note # 212.        */
  37. /*          * Fix minor bug calculating the "thumb" offset base on*/
  38. /*            the contrlValue's handling negative values.        */
  39. /*          8/17/89 asc :                        */
  40. /*          * Fix "thumb" calculation bug. Forget to add "break"    */
  41. /*            to the next "case" statement. Hence, following thru    */
  42. /*            to System 7.0 region calcuation stuff.        */
  43. /*          * Fix problem if the control's rect area has been     */
  44. /*            scrolled. This is not a problem in the "Alternate    */
  45. /*            Demo", but could be in other applications that uses    */
  46. /*            "SetOrigin" to offset it's original rect area. Hence*/
  47. /*            the scroll bar would not be properly offseted.    */
  48. /*          * Re-work the "up" and "down" arrow buttons to use the*/
  49. /*            "altButton" variable to interface into new THINK C's*/
  50. /*            object library.                    */
  51. /*                                    */
  52. /************************************************************************/
  53.  
  54. #include <QuickDraw.h>            /* QuickDraw defs        */
  55. #include <Color.h>            /* Color defs            */
  56. #include <WindowMgr.h>            /* Window Manager defs        */
  57. #include <ControlMgr.h>            /* Control Manager defs        */
  58. #include <ToolBoxUtil.h>        /* Tool Box Utilities defs    */
  59. #include <ColorToolBox.h>        /* Color Tool Box defs        */
  60.  
  61. typedef struct {            /* Dual Control Data Structure    */
  62.    short    hasColor;        /* Has color monitor flag    */
  63.    short    altButton;        /* Using alternate button    */
  64.    Rect        thumb;            /* Thumb rectangle area        */
  65.    Rect        cThumb;            /* Current thumb rectangle area    */
  66.    PolyHandle    up;            /* Up button handle        */
  67.    PolyHandle    down;            /* Down button handle        */
  68.    short    bLen;            /* Button length        */
  69.    short    hBLen;            /* Half button length        */
  70.    short    sLen;            /* Scroll bar length        */
  71.    double    tFactor;        /* Thumb factor            */
  72.    short    hFactor;        /* Horizontal factor        */
  73.    short    vFactor;        /* Vertical factor        */
  74.    ControlHandle cHdl;            /* Control handle to reference    */
  75.    long        blackPat[2];        /* Black pattern        */
  76.    long        ltGrayPat[2];        /* Light gray pattern        */
  77.    } DS;
  78. typedef DS     *DSPTR;
  79. typedef DSPTR    *DSHDL;
  80.  
  81. typedef struct {            /* Thumb Info Data Structure    */
  82.    Rect        limitRect;        /* Limit rect area scrolling    */
  83.    Rect        slopRect;        /* Slop rect area scrolling    */
  84.    short    axis;            /* Drag axis control        */
  85.    } THUMB;
  86. typedef THUMB    *THUMBPTR;
  87.                     /* Misc definitions        */
  88. #define    NIL    (0L)            /* NIL pointer            */
  89. #define    abs(a)    (a<0?-a:a)        /* Absolute macro function    */
  90. #define    min(a,b) (a<b?a:b)        /* Minumim macro function    */
  91. #define    max(a,b) (a<b?b:a)        /* Maximum macro function    */
  92.  
  93.                     /* Trap definitions        */
  94. #define    SysEnvironsTrap    0xa090        /* System Enviorment trap    */
  95. #define    UnknownTrap    0xa89f        /* Unknown trap instruction    */
  96.  
  97.                     /* System 7.0 CDEF messages    */
  98. #define    calcCntlRgn    10        /* Calculate control's region    */
  99. #define    calcThumbRgn    11        /* Calculate "thumb" region    */
  100.  
  101.                     /* Control's macro procedures    */
  102. #define    DSFrameHUpBtn()        DSDrawHBtn(dPtr,dPtr->up,FALSE)
  103. #define    DSFrameHDownBtn()    DSDrawHBtn(dPtr,dPtr->down,FALSE)
  104. #define    DSFrameLUpBtn()        DSDrawLBtn(dPtr,dPtr->up,FALSE)
  105. #define    DSFrameLDownBtn()    DSDrawLBtn(dPtr,dPtr->down,FALSE)
  106. #define    DSFillHUpBtn()        DSDrawHBtn(dPtr,dPtr->up,TRUE)
  107. #define    DSFillHDownBtn()    DSDrawHBtn(dPtr,dPtr->down,TRUE)
  108. #define    DSFillLUpBtn()        DSDrawLBtn(dPtr,dPtr->up,TRUE)
  109. #define    DSFillLDownBtn()    DSDrawLBtn(dPtr,dPtr->down,TRUE)
  110.  
  111. #define    DSFrameBody(a)        DSDrawObject(dPtr->cHdl,DSGetForeGround,DSSetForeGround, \
  112.                          DSFrameRect,cFrameColor,a)
  113. #define    DSClearBody(a)        DSDrawObject(dPtr->cHdl,DSGetBackGround,DSSetBackGround, \
  114.                          DSEraseRect,cBodyColor,a)
  115. #define    DSFillBody(a)        DSDrawObject(dPtr->cHdl,DSGetBackGround,DSSetBackGround, \
  116.                          DSFillRect,cBodyColor,a,dPtr->ltGrayPat)
  117. #define    DSFrameThumb(a)     DSDrawObject(dPtr->cHdl,DSGetForeGround,DSSetForeGround, \
  118.                          DSFrameRect,cFrameColor,a)
  119. #define    DSFillThumb(a)         DSDrawObject(dPtr->cHdl,DSGetBackGround,DSSetBackGround, \
  120.                          DSEraseRect,cThumbColor,a)
  121. #define    DSFrameArrow(a)     DSDrawObject(dPtr->cHdl,DSGetForeGround,DSSetForeGround, \
  122.                          DSFramePoly,cFrameColor,a)
  123. #define    DSClearArrow(a)     DSDrawObject(dPtr->cHdl,DSGetBackGround,DSSetBackGround, \
  124.                          DSErasePoly,cBodyColor,a)
  125. #define    DSFillArrow(a)         DSDrawObject(dPtr->cHdl,DSGetForeGround,DSSetForeGround, \
  126.                          DSFillPoly,cFrameColor,a,dPtr->blackPat)
  127.  
  128.  
  129.                     /* Define forward referneces    */
  130. void    DSInitControl(),DSDrawThumb(),DSPositionThumb(),DSSetupThumb(),
  131.     DSDrawHBtn(),DSDrawLBtn(),DSGetBackGround(),DSGetForeGround(),
  132.     DSSetBackGround(),DSSetForeGround(),DSFrameButtons(),DSEraseRect(),
  133.     DSFrameRect(),DSFillRect(),DSErasePoly(),DSFramePoly(),DSFillPoly(),
  134.     DSDrawObject();
  135. long    DSTestControl();
  136.  
  137. pascal long    main(varCode,theControl,message,param)
  138.  
  139.    short        varCode;    /* Variable control code    */
  140.    ControlHandle     theControl;    /* Control handle        */
  141.    short        message;    /* Control message indicator    */
  142.    register long    param;        /* Control parameter value    */
  143.    
  144.    {
  145.    
  146.       register    ControlPtr cPtr;    /* Working control pointer    */
  147.       DSHDL         dHdl;        /* Working dual control handle    */
  148.       register    DSPTR    dPtr = NIL;    /* Working dual control pointer    */
  149.       Rect        wRect;        /* Working scroll rect area    */
  150.       SysEnvRec        sysEnv;        /* Working system enviroment    */
  151.       long        status = 0;    /* Working status indicator    */
  152.       
  153.       HLock(theControl);        /* Lock down the control handle    */
  154.       
  155.       cPtr = *theControl;        /* Set the control pointer    */
  156.       
  157.       if (message != initCntl) {    /* Check if already initialized    */
  158.       
  159.          if (cPtr->contrlData) {    /* Check if valid handle    */
  160.          
  161.             HLock(cPtr->contrlData);    /* Lock it down for processing    */
  162.          
  163.             dPtr = *((DSHDL)cPtr->contrlData);/* Init dual control pointer*/
  164.          
  165.          }
  166.          
  167.       }
  168.       
  169.       switch(message) {            /* Process the specified message*/
  170.       
  171.          case drawCntl:            /* Draw the control        */
  172.          
  173.             if (dPtr) {            /* Check if dual pointer valid    */
  174.             
  175.                if (cPtr->contrlVis) {    /* Check if control is visible    */
  176.             
  177.                 PenNormal();        /* Setup normal pen characteristics*/
  178.                 
  179.                   switch(LoWord(param)) {/* Switch on control part    */
  180.                
  181.                      case 0:        /* Re-draw scroll bar        */
  182.                   
  183.                       DSInitControl(dPtr,cPtr);/* Re-init it        */
  184.                       
  185.                               /* Init the scroll bar        */
  186.                         DSFrameBody(&cPtr->contrlRect);
  187.                         
  188.                         DSFrameButtons(dPtr);/* Frame the buttons    */
  189.                         DSFrameHUpBtn();
  190.                         DSFrameHDownBtn();
  191.                         DSFrameLUpBtn();
  192.                         DSFrameLDownBtn();
  193.                            
  194.             DSDrawThumb(dPtr,theControl);
  195.                         
  196.                         break;
  197.                         
  198.                      case 129:        /* Value/Min/Max changed    */
  199.                   
  200.             DSDrawThumb(dPtr,theControl);
  201.                 
  202.                         break;
  203.                      
  204.                      case 0xff:        /* Control to be inactive    */
  205.                           
  206.                       DSSetScrollRgn(dPtr,&wRect);/* Set scroll region*/
  207.                              
  208.             DSClearBody(&wRect);/* Clear scroll bar        */
  209.                
  210.                         break;
  211.                      
  212.                      case inPageUp:    /* Hilite scroll bar        */
  213.                      case inPageDown:
  214.                      
  215.             DSDrawThumb(dPtr,theControl);
  216.                         
  217.                         break;
  218.                                    
  219.                      case inUpButton:    /* Hilite the high up button    */
  220.                   
  221.                       if (dPtr->altButton) {/* Check if alt button    */
  222.                if (cPtr->contrlHilite == 0 ||
  223.                    cPtr->contrlMin == cPtr->contrlMax)
  224.                   DSFrameLUpBtn();
  225.                else
  226.                               DSFillLUpBtn();
  227.                       }
  228.                       
  229.                       else {        /* Nope, using regular button    */
  230.                if (cPtr->contrlHilite == 0 ||
  231.                    cPtr->contrlMin == cPtr->contrlMax)
  232.                   DSFrameHUpBtn();
  233.                else
  234.                               DSFillHUpBtn();
  235.                         }
  236.                                                    
  237.                         break;
  238.                                    
  239.                      case inDownButton:/* Hilite the high down button    */
  240.                   
  241.                       if (dPtr->altButton) {/* Check if alt button    */
  242.                if (cPtr->contrlHilite == 0 ||
  243.                    cPtr->contrlMin == cPtr->contrlMax)
  244.                   DSFrameLDownBtn();
  245.                else
  246.                               DSFillLDownBtn();
  247.                         }
  248.                         
  249.                         else {        /* Nope, using regular button    */
  250.                if (cPtr->contrlHilite == 0 ||
  251.                    cPtr->contrlMin == cPtr->contrlMax)
  252.                   DSFrameHDownBtn();
  253.                else
  254.                               DSFillHDownBtn();
  255.                         }
  256.                                                    
  257.                   }
  258.                               
  259.                }
  260.             
  261.             }
  262.             
  263.             break;
  264.             
  265.          case testCntl:            /* Test the control        */
  266.          
  267.             if (dPtr) {            /* Check if dual pointer valid    */
  268.             
  269.                if (cPtr->contrlHilite != -1) {/* Check if control active*/
  270.             
  271.                             /* Check if valid to process    */
  272.                   if (cPtr->contrlMin != cPtr->contrlMax) {
  273.  
  274.                             /* Check if within the rect area*/
  275.                      if (PtInRect(param,&cPtr->contrlRect))
  276.                         status = DSTestControl(dPtr,param);/* Find part    */
  277.                   
  278.                   }
  279.                   
  280.                }
  281.             
  282.             }
  283.             
  284.             break;
  285.             
  286.          case calcCRgns:        /* Calculate control's region    */
  287.          
  288.             if (dPtr) {            /* Check if dual pointer valid    */
  289.             
  290.                if (!(param & 0x80000000L))/* Check if want whole control*/
  291.                   RectRgn((Handle)(param & 0x7fffffffL),&cPtr->contrlRect);
  292.                  
  293.                else {            /* Want thumb's region        */
  294.  
  295.                             /* Setup thumb's region area    */
  296.                   RectRgn((Handle)(param & 0x7fffffffL),&dPtr->cThumb);
  297.                   
  298.                               /* Setup drag pattern        */
  299.                   BlockMove(dPtr->ltGrayPat,DragPattern,8L);
  300.                   
  301.                }
  302.                
  303.             }
  304.             
  305.             break;
  306.             
  307.          case calcCntlRgn:        /* Calculate control's region    */
  308.          
  309.             if (dPtr)             /* Check if dual pointer valid    */
  310.                RectRgn((Handle)(param),&cPtr->contrlRect);
  311.                
  312.             break;
  313.             
  314.          case calcThumbRgn:        /* Calculate "thumb" region    */
  315.  
  316.             if (dPtr) {            /* Check if dual pointer valid    */
  317.             
  318.                             /* Setup thumb's region area    */
  319.                RectRgn((Handle)(param),&dPtr->cThumb);
  320.                   
  321.                               /* Setup drag pattern        */
  322.                BlockMove(dPtr->ltGrayPat,DragPattern,8L);
  323.             
  324.             }
  325.             
  326.             break;
  327.             
  328.          case initCntl:            /* Initialized the control    */
  329.          
  330.                          /* Allocate the data handle    */
  331.             if (dHdl = (DSHDL)NewHandle(sizeof(DS))) {
  332.             
  333.                HLock(dHdl);        /* Lock it down for initialization*/
  334.                
  335.                dPtr = *dHdl;        /* Set dual control pointer    */
  336.                
  337.                dPtr->cHdl = theControl;    /* Save control for referencing    */
  338.                
  339.                dPtr->up = dPtr->down = NIL;/* Init the poly handles    */
  340.                
  341.                                /* Init the patterns        */
  342.                  dPtr->blackPat[0] = dPtr->blackPat[1] = 0xffffffffL;
  343.                  dPtr->ltGrayPat[0] = dPtr->ltGrayPat[1] = 0x88228822L;
  344.       
  345.                  dPtr->hasColor = FALSE;    /* Set default to black & white    */
  346.                  
  347.                  dPtr->altButton = FALSE;    /* Set not using alternate button*/
  348.                  
  349.                           /* Check if SysEnvirons valid    */
  350.                if ((long)NGetTrapAddress(SysEnvironsTrap,OSTrap) != 
  351.                     (long)NGetTrapAddress(UnknownTrap,ToolTrap)) {
  352.                      
  353.            SysEnvirons(1,&sysEnv);/* Get system enviroment    */
  354.                     
  355.            dPtr->hasColor = sysEnv.hasColorQD;/* Save color    */
  356.              
  357.            }
  358.            
  359.                DSInitControl(dPtr,cPtr);/* Init the control's parameters*/
  360.                     
  361.                cPtr->contrlAction = (ProcPtr)(-1L);/* Set default action*/
  362.                      
  363.                cPtr->contrlData = (Handle)dHdl;/* Save the data handle    */
  364.                
  365.             }
  366.             
  367.             break;
  368.             
  369.          case dispCntl:            /* Dispose the control        */
  370.          
  371.             if (dPtr) {            /* Check if dual pointer valid    */
  372.             
  373.                if (dPtr->up)        /* Kill the polys        */
  374.                   KillPoly(dPtr->up);
  375.                if (dPtr->down)
  376.                   KillPoly(dPtr->down);
  377.             
  378.                HUnlock(cPtr->contrlData);/* Unlock it for releasing    */
  379.             
  380.                DisposHandle(cPtr->contrlData);/* Release back memory mgr*/
  381.             
  382.             }
  383.             
  384.             cPtr->contrlData = NIL;    /* Clear it            */
  385.             
  386.             break;
  387.             
  388.          case posCntl:            /* Re-position the control    */
  389.          
  390.             if (dPtr)            /* Check if dual pointer valid    */
  391.                DSPositionThumb(dPtr,theControl,param);
  392.             
  393.             break;
  394.             
  395.          case thumbCntl:        /* Calculate thumb for dragging    */
  396.          
  397.             if (dPtr)            /* Check if dual pointer valid    */
  398.                DSSetupThumb(dPtr,param);/* Setup thumb for dragging    */
  399.             
  400.             break;
  401.             
  402.          case dragCntl:            /* Drag the control        */
  403.          
  404.             status = 0;            /* Only drag thumb!        */
  405.  
  406.             break;
  407.             
  408.          case autoTrack:        /* Execute control's action    */
  409.          
  410.             break;
  411.             
  412.       }
  413.             
  414.       if (cPtr->contrlData)        /* Check if valid pointer    */
  415.          HUnlock(cPtr->contrlData);    /* Unlock for memory manager    */
  416.       
  417.       HUnlock(theControl);        /* Unlock the control handle    */
  418.       
  419.       return(status);            /* Return status code        */
  420.       
  421.    }
  422.  
  423. void    DSInitControl(dPtr,cPtr)
  424.  
  425.    register DSPTR    dPtr;        /* Dual control pointer        */
  426.    register ControlPtr    cPtr;        /* Control pointer        */
  427.    
  428.    {
  429.    
  430.       register    PolyHandle pHdl;    /* Working poly handle        */
  431.       register    short    bLen;        /* Working button length    */
  432.       register    short    hBLen;        /* Working half button length    */
  433.       register    short    hLen;        /* Working horizontal length    */
  434.       short        vLen;        /* Working vertical length    */
  435.       register    short    tmp1,tmp2;    /* Working temporary variables    */
  436.       Rect        cRect;        /* Working control rect area    */
  437.  
  438.       cRect = cPtr->contrlRect;        /* Set scroll bar area        */
  439.                
  440.       InsetRect(&cRect,1,1);        /* Shrink it by one-pixel    */
  441.                
  442.       hLen = abs(cRect.right - cRect.left) + 1;/* Set horizontal length    */
  443.                                 
  444.       vLen = abs(cRect.bottom - cRect.top) + 1;/* Set vertical length    */
  445.                
  446.       if (hLen > vLen) {        /* Check if horizontal is longer*/
  447.  
  448.      dPtr->bLen = vLen;        /* Set button length        */
  449.                   
  450.          dPtr->sLen = hLen + 1;        /* Set scroll bar length    */
  451.          
  452.          dPtr->hFactor = 1;        /* Set horizontal factor    */
  453.          
  454.          dPtr->vFactor = 0;        /* Set vertical factor        */
  455.          
  456.       }
  457.                
  458.       else {                /* Nope, must be vertical    */
  459.                
  460.          dPtr->bLen = hLen;        /* Set button length        */
  461.                   
  462.          dPtr->sLen = vLen + 1;        /* Set scroll bar length    */
  463.          
  464.          dPtr->hFactor = 0;        /* Set horizontal factor    */
  465.          
  466.          dPtr->vFactor = 1;        /* Set vertical factor        */
  467.          
  468.       }
  469.                
  470.       bLen = dPtr->bLen;        /* Set button length        */
  471.       
  472.       hBLen = dPtr->hBLen = bLen / 2;    /* Set half button length    */
  473.                
  474.       dPtr->thumb.top = dPtr->thumb.left = 0;/* Init top.left point    */
  475.                
  476.       if (dPtr->hFactor) {        /* Check if horizontal position    */
  477.                   
  478.          dPtr->thumb.bottom = bLen - 1;
  479.          dPtr->thumb.right = hBLen + hBLen / 2;
  480.                      
  481.       }
  482.                   
  483.       else {                /* Nope, it's vertical position    */
  484.                   
  485.          dPtr->thumb.bottom = hBLen + hBLen / 2;
  486.          dPtr->thumb.right = bLen - 1;
  487.                      
  488.       }
  489.                   
  490.       tmp1 = hBLen - 1;            /* Set temporary calculations    */
  491.       tmp2 = hBLen - 2;
  492.             
  493.                                /* Create up poly handle    */
  494.       if (pHdl = OpenPoly()) {        /* Check if got a poly handle    */
  495.                
  496.          if (dPtr->hFactor) {        /* Check horizontal position    */
  497.                   
  498.             MoveTo(0,tmp1);
  499.             LineTo(tmp2,tmp2 * 2 + 1);
  500.             LineTo(tmp2,1);
  501.             LineTo(0,tmp1);
  502.                   
  503.          }
  504.                   
  505.          else {                /* Nope, it's vertical position    */
  506.                   
  507.             MoveTo(tmp1,0);
  508.             LineTo(1,tmp2);
  509.             LineTo(tmp2 * 2 + 1,tmp2);
  510.             LineTo(tmp1,0);
  511.                      
  512.          }
  513.                   
  514.          ClosePoly();            /* Close the poly handle    */
  515.                   
  516.       }
  517.                
  518.       if (dPtr->up)            /* Check if have old poly handle*/
  519.          KillPoly(dPtr->up);        /* Release this poly handle    */
  520.          
  521.       dPtr->up = pHdl;            /* Set up poly handle        */
  522.                
  523.                                /* Create down poly handle    */
  524.       if (pHdl = OpenPoly()) {        /* Check if got a poly handle    */
  525.                
  526.          if (dPtr->hFactor) {        /* Check horizontal position    */
  527.                   
  528.             MoveTo(tmp2,tmp1);
  529.             LineTo(0,tmp2 * 2 + 1);
  530.             LineTo(0,1);
  531.             LineTo(tmp2,tmp1);
  532.             
  533.             OffsetPoly(pHdl,hBLen,0);
  534.             
  535.          }
  536.                   
  537.          else {                /* Nope, it's vertical position    */
  538.                   
  539.             MoveTo(1,0);
  540.             LineTo(tmp2 * 2 + 1,0);
  541.             LineTo(tmp1,tmp1);
  542.             LineTo(1,0);
  543.                 
  544.             OffsetPoly(pHdl,0,hBLen);
  545.                  
  546.          }
  547.                   
  548.          ClosePoly();            /* Close the poly handle    */
  549.                   
  550.       }
  551.                
  552.       if (dPtr->down)            /* Check if have old poly handle*/
  553.          KillPoly(dPtr->down);        /* Release this poly handle    */
  554.          
  555.       dPtr->down = pHdl;        /* Set down poly handle        */
  556.                
  557.    }
  558.    
  559. void    DSCalcThumb(dPtr,cPtr)
  560.  
  561.    register DSPTR    dPtr;        /* Dual control pointer        */
  562.    register ControlPtr    cPtr;        /* Control pointer        */
  563.    
  564.    {
  565.    
  566.       double        tmp1,tmp2;    /* Working temporary registers    */
  567.       register short    offset;        /* Working pixel offset        */
  568.       Rect        wRect;        /* Working scroll rect area    */
  569.       
  570.                           /* Make sure this is mimimum    */
  571.       cPtr->contrlMin = min(cPtr->contrlMin,cPtr->contrlMax);
  572.       
  573.                           /* Make sure this is maximum    */
  574.       cPtr->contrlMax = max(cPtr->contrlMin,cPtr->contrlMax);
  575.       
  576.                           /* Make sure min < value < max    */
  577.       cPtr->contrlValue = min(cPtr->contrlMax,
  578.                         max(cPtr->contrlMin,cPtr->contrlValue));
  579.             
  580.       DSSetScrollRgn(dPtr,&wRect);    /* Set scroll region        */
  581.       
  582.                             /* Setup thumb factor calculation*/
  583.       tmp1 = max(abs(wRect.bottom - wRect.top) * dPtr->vFactor,
  584.                  abs(wRect.right - wRect.left) * dPtr->hFactor) - 
  585.                  dPtr->bLen + dPtr->hBLen - 2;
  586.       tmp2 = abs(cPtr->contrlMax - cPtr->contrlMin);
  587.       
  588.       dPtr->tFactor = tmp1 / tmp2;    /* Set relative thumb factor    */
  589.       
  590.                           /* Compute thumb pixel offset    */
  591.       tmp1 = cPtr->contrlValue - cPtr->contrlMin;        
  592.       tmp2 = tmp1 * dPtr->tFactor;
  593.       offset = tmp2;
  594.       
  595.       dPtr->cThumb = dPtr->thumb;    /* Set the thumb rect area    */ 
  596.       OffsetRect(&dPtr->cThumb,wRect.left + offset * dPtr->hFactor,
  597.                          wRect.top + offset * dPtr->vFactor);
  598.                            
  599.    }
  600.  
  601. void    DSDrawThumb(dPtr,cHdl)
  602.  
  603.    register DSPTR    dPtr;        /* Dual control pointer        */
  604.    register ControlHandle cHdl;        /* Control handle        */
  605.    
  606.    {
  607.    
  608.       Rect    tRect;            /* Working thumb rect area    */
  609.       ControlPtr cPtr = *cHdl;        /* Working control pointer    */
  610.             
  611.       DSSetScrollRgn(dPtr,&tRect);    /* Set scroll region        */
  612.          
  613.       if (cPtr->contrlHilite != 255 &&    /* Check if can show thumb    */
  614.       cPtr->contrlMax > cPtr->contrlMin) {
  615.  
  616.          DSCalcThumb(dPtr,cPtr);    /* Re-calculate thumb        */
  617.                         
  618.          ForeColor((long)(blackColor));    /* Make sure it's black & white    */
  619.          BackColor((long)(whiteColor));
  620.          
  621.          DSFillBody(&tRect);        /* Fill in scroll bar        */
  622.     
  623.          tRect = dPtr->cThumb;        /* Set thumb rect area        */
  624.       
  625.          DSFrameThumb(&tRect);        /* Frame thumb            */
  626.                         
  627.          InsetRect(&tRect,1,1);        /* Inset by one pixel        */
  628.       
  629.          DSFillThumb(&tRect);        /* Clear inside of the thumb    */
  630.          
  631.       }
  632.       
  633.       else                /* Nope, don't want scroll region*/
  634.          DSClearBody(&tRect);        /* Clear scroll region        */
  635.       
  636.    }
  637.    
  638. void    DSPositionThumb(dPtr,cHdl,pt)
  639.  
  640.    register DSPTR    dPtr;        /* Dual control pointer        */
  641.    register ControlHandle cHdl;        /* Control handle        */
  642.    register Point    pt;        /* Point position of the thumb    */
  643.    
  644.    {
  645.    
  646.       register double    offset;        /* Working value offset        */
  647.       
  648.       if (dPtr->hFactor)        /* Check if it's horizontal    */
  649.          offset = pt.h;            /* Use horizontal offset    */
  650.          
  651.       else                /* Nope, it's vertical        */
  652.          offset = pt.v;            /* Use vertical offset        */
  653.          
  654.       offset = offset / dPtr->tFactor;    /* Reset the control's value    */
  655.       (*cHdl)->contrlValue += offset;
  656.          
  657.       DSDrawThumb(dPtr,cHdl);        /* Draw da thumb, again!    */
  658.                
  659.    }
  660.    
  661. void    DSSetupThumb(dPtr,thumbPtr)
  662.  
  663.    register DSPTR    dPtr;        /* Dual control pointer        */
  664.    register THUMBPTR    thumbPtr;    /* Thumb's info pointer        */
  665.    
  666.    {
  667.    
  668.       register Point    msePt;        /* Working mouse point        */
  669.       
  670.       msePt.h = thumbPtr->limitRect.left;/* Save current mouse down    */
  671.       msePt.v = thumbPtr->limitRect.top;
  672.       
  673.       DSSetScrollRgn(dPtr,&thumbPtr->limitRect);/* Set scroll region    */
  674.       
  675.       if (dPtr->hFactor) {        /* Check if horizontal scroll bar*/
  676.       
  677.                           /* Adjust it for mouse position    */
  678.          thumbPtr->limitRect.left += msePt.h - dPtr->cThumb.left;
  679.          thumbPtr->limitRect.right -= dPtr->cThumb.right - msePt.h - 1;
  680.       
  681.                          /* Set slop rect area        */
  682.          thumbPtr->slopRect.top = thumbPtr->limitRect.top - 16;
  683.          thumbPtr->slopRect.bottom = thumbPtr->limitRect.bottom + 16;
  684.          thumbPtr->slopRect.left = -32000; thumbPtr->slopRect.right = 32000;
  685.          
  686.          thumbPtr->axis = hAxisOnly;    /* Set axis dragging direction    */
  687.                        
  688.       }
  689.       
  690.       else {                /* Nope, it's vertical scroll bar*/
  691.       
  692.                           /* Adjust it for mouse position    */
  693.          thumbPtr->limitRect.top += msePt.v - dPtr->cThumb.top;
  694.          thumbPtr->limitRect.bottom -= dPtr->cThumb.bottom - msePt.v - 1;
  695.  
  696.                          /* Set slop rect area        */
  697.          thumbPtr->slopRect.left = thumbPtr->limitRect.left - 16;
  698.          thumbPtr->slopRect.right = thumbPtr->limitRect.right + 16;
  699.          thumbPtr->slopRect.top = -32000; thumbPtr->slopRect.bottom = 32000;
  700.       
  701.          thumbPtr->axis = vAxisOnly;    /* Set axis dragging direction    */
  702.                        
  703.       }
  704.       
  705.    }
  706.    
  707. void    DSDrawHBtn(dPtr,btn,fill)
  708.  
  709.    register DSPTR    dPtr;        /* Dual control pointer        */
  710.    register PolyHandle    btn;        /* Poly button handle        */
  711.    short        fill;        /* Fill flag indicator        */
  712.    
  713.    {
  714.    
  715.                               /* Offset where button        */
  716.       OffsetPoly(btn,(*dPtr->cHdl)->contrlRect.left + 1,
  717.                    (*dPtr->cHdl)->contrlRect.top + 1);
  718.                
  719.       if (fill)                /* Check if filling the arrow    */
  720.          DSFillArrow(btn);        /* Fill in the arrow button    */
  721.          
  722.       else                /* Nope, not clearing it    */
  723.          DSClearArrow(btn);        /* Clear the arrow button    */
  724.          
  725.       DSFrameArrow(btn);        /* Frame the arrow button    */
  726.                       
  727.                              /* Restore the button        */
  728.       OffsetPoly(btn,-(*dPtr->cHdl)->contrlRect.left - 1,
  729.                    -(*dPtr->cHdl)->contrlRect.top - 1);
  730.  
  731.    }
  732.  
  733. void    DSDrawLBtn(dPtr,btn,fill)
  734.  
  735.    register DSPTR    dPtr;        /* Dual control pointer        */
  736.    register PolyHandle    btn;        /* Poly button handle        */
  737.    short        fill;        /* Fill flag indicator        */
  738.    
  739.    {
  740.    
  741.       register short    tmp1,tmp2;    /* Working temporary variables    */
  742.       register short    offset;        /* Working offset        */
  743.       
  744.       offset = dPtr->sLen - dPtr->bLen - 1;/* Set relative offset    */
  745.       
  746.                               /* Offset where button        */
  747.       OffsetPoly(btn,tmp1 = (*dPtr->cHdl)->contrlRect.left + 
  748.                        dPtr->hFactor * offset + 1,
  749.                      tmp2 = (*dPtr->cHdl)->contrlRect.top + 
  750.                               dPtr->vFactor * offset + 1);
  751.                       
  752.       if (fill)                /* Check if filling the arrow    */
  753.          DSFillArrow(btn);        /* Fill in the arrow button    */
  754.          
  755.       else                /* Nope, not clearing it    */
  756.          DSClearArrow(btn);        /* Clear the arrow button    */
  757.          
  758.       DSFrameArrow(btn);        /* Frame the arrow button    */
  759.  
  760.       OffsetPoly(btn,-tmp1,-tmp2);    /* Restore the button        */
  761.  
  762.    }
  763.  
  764. void    DSFrameButtons(dPtr)
  765.  
  766.    register DSPTR    dPtr;        /* Dual control pointer        */
  767.    
  768.    {
  769.    
  770.       Rect    bRect;            /* Working box rect area    */
  771.       register    short    offset;        /* Working low button offset    */
  772.       
  773.       bRect.left = bRect.top = 0;    /* Set left-top point        */
  774.       
  775.       bRect.right = bRect.bottom = dPtr->bLen + 1;/* Set right-top point*/
  776.       
  777.                           /* Offset the high button box    */
  778.       OffsetRect(&bRect,(*dPtr->cHdl)->contrlRect.left,
  779.                   (*dPtr->cHdl)->contrlRect.top);
  780.       
  781.       DSClearBody(&bRect);        /* Clear the body part        */
  782.       
  783.       DSFrameBody(&bRect);        /* Frame the high button box    */
  784.       
  785.       offset = dPtr->sLen - dPtr->bLen - 1;/* Set low button box offset    */
  786.       
  787.                           /* Offset the low button box    */
  788.       OffsetRect(&bRect,dPtr->hFactor * offset,dPtr->vFactor * offset);
  789.       
  790.       DSClearBody(&bRect);        /* Clear the body part        */
  791.       
  792.       DSFrameBody(&bRect);        /* Frame the low button box    */
  793.       
  794.    }
  795.  
  796. long    DSTestControl(dPtr,pt)
  797.  
  798.    register DSPTR    dPtr;        /* Dual control pointer        */
  799.    Point        pt;        /* Point position        */
  800.    
  801.    {
  802.    
  803.       register    Rect    cRect;        /* Working control rect area    */
  804.       register    Rect    tRect;        /* Working temp rect area    */
  805.       Rect        bRect;        /* Working button rect area    */
  806.       register    short    offset;        /* Working offset        */
  807.       short        point;        /* Working point in region    */
  808.       long        status = 0;    /* Working status indicator    */
  809.       
  810.       cRect = (*dPtr->cHdl)->contrlRect;/* Set working control rect area*/
  811.       
  812.       bRect = dPtr->thumb;        /* Set the button rect area    */
  813.       
  814.       if (dPtr->hFactor)        /* Check if horizontal button    */
  815.          bRect.right = dPtr->hBLen;    /* Adjust for horizontal button    */
  816.       
  817.       else
  818.          bRect.bottom = dPtr->hBLen;    /* Adjust for vertical button    */
  819.          
  820.       tRect = bRect;            /* Set the temp rect area    */
  821.                    
  822.       OffsetRect(&tRect,cRect.left,cRect.top);/* Offset where high up btn*/
  823.                       
  824.       if (PtInRect(pt,&tRect)) {    /* Check if in high up button    */
  825.          status = inUpButton;        /* Set high up button        */
  826.          dPtr->altButton = FALSE;    /* Set not using alternate button*/
  827.       }
  828.          
  829.       if (!status) {            /* Check if previous part control*/
  830.                       
  831.                               /* Adjust for down button    */
  832.          OffsetRect(&tRect,dPtr->hFactor * dPtr->hBLen,
  833.                     dPtr->vFactor * dPtr->hBLen);
  834.                          
  835.          if (PtInRect(pt,&tRect)) {    /* Check if the high down button*/
  836.             status = inDownButton;    /* Set high down button        */
  837.             dPtr->altButton = FALSE;    /* Set not using alternate button*/
  838.          }
  839.       }
  840.       
  841.       if (!status) {            /* Check if previous part control*/
  842.          
  843.          tRect = bRect;            /* Set the temp rect area    */
  844.                               
  845.          offset = dPtr->sLen - dPtr->bLen;/* Set relative offset    */
  846.          
  847.                               /* Offset where low up button    */
  848.          OffsetRect(&tRect,cRect.left + dPtr->hFactor * offset,
  849.                     cRect.top + dPtr->vFactor * offset);
  850.                       
  851.          if (PtInRect(pt,&tRect)) {    /* Check if the low up button    */
  852.             status = inUpButton;    /* Set low up button        */
  853.             dPtr->altButton = TRUE;    /* Set using alternate button    */
  854.          }
  855.       }
  856.                         
  857.       if (!status) {            /* Check if previous part control*/
  858.          
  859.                          /* Offset where low down button    */
  860.          OffsetRect(&tRect,dPtr->hFactor * dPtr->hBLen,
  861.                     dPtr->vFactor * dPtr->hBLen);
  862.                       
  863.          if (PtInRect(pt,&tRect)) {    /* Check if the low down button    */
  864.             status = inDownButton;    /* Set low down button        */
  865.             dPtr->altButton = TRUE;    /* Set using alternate button    */
  866.          }
  867.       }
  868.                         
  869.       if (!status) {            /* Check if previous part control*/
  870.       
  871.          if (PtInRect(pt,&dPtr->cThumb))/* Check if in thumb        */
  872.             status = inThumb;        /* Set thumb part        */
  873.  
  874.       }
  875.       
  876.       if (!status) {            /* Check if previous part control*/
  877.        
  878.                            /* Set relative point        */
  879.          point = pt.h * dPtr->hFactor + pt.v * dPtr->vFactor;
  880.          
  881.                          /* Set relative offset        */
  882.          offset = dPtr->cThumb.left * dPtr->hFactor + 
  883.                   dPtr->cThumb.top * dPtr->vFactor;
  884.                               
  885.          if (point > offset)        /* Check if in down page region    */
  886.             status = inPageDown;    /* Set down page region        */
  887.             
  888.          else
  889.             status = inPageUp;        /* Set up page region        */
  890.             
  891.       }
  892.        
  893.       return(status);            /* Return status indicator    */
  894.       
  895.    }
  896.    
  897. DSSetScrollRgn(dPtr,scrollRgn)
  898.  
  899.    register DSPTR    dPtr;        /* Dual control pointer        */
  900.    register Rect    *scrollRgn;    /* Scrolling region area    */
  901.    
  902.    {
  903.    
  904.       *scrollRgn = (*dPtr->cHdl)->contrlRect;/* Set scroll region area    */
  905.       
  906.       InsetRect(scrollRgn,1,1);        /* Shrink it a bit        */
  907.       
  908.       if (dPtr->hFactor) {        /* Check if horizontal bar    */
  909.            
  910.      scrollRgn->left += dPtr->bLen;    /* Adjust the rect area        */
  911.      scrollRgn->right -= dPtr->bLen;
  912.            
  913.       }
  914.            
  915.       else {                /* It's a vertical scroll bar    */
  916.            
  917.      scrollRgn->top += dPtr->bLen;    /* Adjust the rect area        */
  918.      scrollRgn->bottom -= dPtr->bLen;
  919.  
  920.       }
  921.       
  922.    }
  923.    
  924. void    DSGetBackGround(color) RGBColor    *color; { GetBackColor(color); }
  925. void    DSGetForeGround(color) RGBColor    *color; { GetForeColor(color); }
  926. void    DSSetBackGround(color) RGBColor    *color; { RGBBackColor(color); }
  927. void    DSSetForeGround(color) RGBColor    *color; { RGBForeColor(color); }
  928.    
  929. void    DSEraseRect(rect) Rect *rect; { EraseRect(rect); }
  930. void    DSFrameRect(rect) Rect *rect; { FrameRect(rect); }
  931. void    DSFillRect(rect,pattern) Rect *rect; Pattern *pattern;
  932.         { FillRect(rect,pattern); }
  933. void    DSErasePoly(poly) PolyHandle poly; { ErasePoly(poly); }
  934. void    DSFramePoly(poly) PolyHandle poly; { FramePoly(poly); }
  935. void    DSFillPoly(poly,pattern) PolyHandle poly; Pattern *pattern;
  936.         { FillPoly(poly,pattern); }
  937.  
  938. void    DSDrawObject(cHdl,getGround,setGround,object,color,arg1,arg2)
  939.  
  940.    ControlHandle cHdl;            /* Control handle        */
  941.    ProcPtr    getGround;        /* Get back/fore ground proc    */
  942.    ProcPtr    setGround;        /* Set back/fore ground proc    */
  943.    ProcPtr    object;            /* Draw object proc        */
  944.    short    color;            /* Color index            */
  945.    long        arg1,arg2;        /* Argument's parameters    */
  946.    
  947.    {
  948.    
  949.        AuxCtlHndl    acHdl = NIL;    /* Working aux color handle    */
  950.        RGBColor        oldColor;    /* Working old color        */
  951.        RGBColor        newColor;    /* Working new color        */
  952.        
  953.                            /* Check if has color monitor    */
  954.        if ((*((DSHDL)((*cHdl)->contrlData)))->hasColor) {
  955.        
  956.           GetAuxCtl(cHdl,&acHdl);    /* Get control's color info    */
  957.        
  958.           if (acHdl) {            /* Check if really got it!    */
  959.        
  960.              (*getGround)(&oldColor);    /* Get original back-ground color*/
  961.           
  962.                           /* Get body's color        */
  963.              newColor = (*(*acHdl)->acCTable)->ctTable[color].rgb;
  964.                           
  965.              (*setGround)(&newColor);    /* Set to control's body color    */
  966.           
  967.           }
  968.        
  969.        }
  970.        
  971.        (*object)(arg1,arg2);        /* Draw the object        */
  972.        
  973.        if (acHdl)             /* Check if have aux color info    */
  974.           (*setGround)(&oldColor);    /* Restore back-ground color    */
  975.           
  976.    }
  977.    
  978.